package fr.leava.domain;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Created by IntelliJ IDEA.
 * User: 417456
 * Date: 2/3/12
 * Time: 12:35 PM
 */
public class RSSReader {

    public static final Logger LOGGER = Logger.getLogger(RSSReader.class.getName());

    /**
     * Parser le fichier XML
     *
     * @param feedurl URL du flux RSS
     * @return a RSSFeed object
     */
    public RSSFeed parse(String feedurl) {
        final RSSFeed rssFeed = new RSSFeed();
        rssFeed.setRssItems(new ArrayList<RSSItem>());

        try {
            final DocumentBuilder builder;
            final URL url;
            final InputStream inputStream;
            final Document doc;
            NodeList nodes;
            NodeList enclosureNodes;
            final Node node;

            builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            url = new URL(feedurl);
            inputStream = retrieveInputStream(url);
            doc = builder.parse(inputStream);
            nodes = null;
            /**
             * Titre et date du flux
             */
            nodes = doc.getElementsByTagName("title");
            node = doc.getDocumentElement();
            rssFeed.setTitle(this.readNode(node, "channel|title"));
            rssFeed.setDescription(this.readNode(node, "channel|description"));
            rssFeed.setLastBuildDate(this.readNode(node, "channel|title"));
            rssFeed.setLink(this.readNode(node, "channel|link"));
            if (LOGGER.isLoggable(Level.ALL)) {
                LOGGER.log(Level.FINEST, "Flux RSS: " + this.readNode(node, "channel|title"));
                LOGGER.log(Level.FINEST, "Date de publication: " + GMTDateToFrench(this.readNode(node, "channel|lastBuildDate")));
            }
            /**
             * Elements du flux RSS
             **/
            nodes = doc.getElementsByTagName("item");
            enclosureNodes = doc.getElementsByTagName("enclosure");
            for (int i = 0; i < nodes.getLength(); i++) {
                final Element element;
                final RSSItem rssItem;
                final RSSEnclosure rssEnclosure;
                final Element enclosureElement;
                element = (Element) nodes.item(i);
                enclosureElement = (Element) enclosureNodes.item(i); // TODO refactor this very very dirty code ; indeed we have no guarantee that the n-th enclosure element is related to the n-th item element
                rssItem = new RSSItem();

                rssItem.setTitle(readNode(element, "title"));
                rssItem.setLink(readNode(element, "link"));
                rssItem.setPubDate(readNode(element, "pubDate"));
                rssItem.setDescription(readNode(element, "description"));

                rssEnclosure = new RSSEnclosure();

                rssEnclosure.setUrl(enclosureElement.getAttribute("url"));
//                rssEnclosure.setLength(Integer.parseInt(element.getAttribute("length")));
                rssEnclosure.setType(enclosureElement.getAttribute("type"));

                rssItem.setRssEnclosure(rssEnclosure);

                rssFeed.getRssItems().add(rssItem);

            } //for
            //for
        } catch (SAXException ex) {
            LOGGER.log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            LOGGER.log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException ex) {
            LOGGER.log(Level.SEVERE, null, ex);
        }
        return rssFeed;
    }

    private InputStream retrieveInputStream(URL url) throws IOException {
        InputStream inputStream;
//         TODO restore
        inputStream = url.openStream();
        return inputStream;
        /*final byte[] bytes = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n" +
                "<rss version=\"2.0\"> \n" +
                "\t<channel> \n" +
                "\t\t<title>Leava.fr - Pensée Juive</title> \n" +
                "\t\t<description>Leava.fr - La flamme (Leava)</description> \n" +
                "\t\t<lastBuildDate>Wed, 01 Feb 2012 14:58:48 +0100</lastBuildDate> \n" +
                "\t\t<link>http://www.leava.fr</link> \n" +
                "<item> \n" +
                "\t<title>Paracha Bo - La sortie d'Egypte</title> \n" +
                "\t<description>Paracha Bo - La sortie d'Egypte</description> \n" +
                "\t<pubDate>Sun, 29 Jan 2012 20:09:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/699_paracha-bo-la-sortie-d-egypte.php</link> \n" +
                "\t<guid>LEAVA-COURS-699</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/rav-benhayoun-120-90.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>Blessé</title> \n" +
                "\t<description>Blessé</description> \n" +
                "\t<pubDate>Thu, 26 Jan 2012 14:39:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/697_blesse.php</link> \n" +
                "\t<guid>LEAVA-COURS-697</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/114.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>Hachem récompense les mécréants</title> \n" +
                "\t<description>Hachem récompense les mécréants</description> \n" +
                "\t<pubDate>Sun, 22 Jan 2012 19:21:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/696_hachem-recompense-les-mecreants.php</link> \n" +
                "\t<guid>LEAVA-COURS-696</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/111.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>Le kif désintéressé</title> \n" +
                "\t<description>Le kif désintéressé</description> \n" +
                "\t<pubDate>Fri, 20 Jan 2012 06:00:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/695_le-kif-desinteresse.php</link> \n" +
                "\t<guid>LEAVA-COURS-695</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/112.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>La paresse</title> \n" +
                "\t<description>La paresse</description> \n" +
                "\t<pubDate>Wed, 18 Jan 2012 16:36:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/694_la-paresse.php</link> \n" +
                "\t<guid>LEAVA-COURS-694</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/rav-y-abergel2011-120x67.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>La perruque</title> \n" +
                "\t<description>La perruque</description> \n" +
                "\t<pubDate>Mon, 16 Jan 2012 16:55:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/693_la-perruque.php</link> \n" +
                "\t<guid>LEAVA-COURS-693</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/07.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>Que savait Moché de la Torah des rabbins?</title> \n" +
                "\t<description>Que savait Moché de la Torah des rabbins?</description> \n" +
                "\t<pubDate>Thu, 12 Jan 2012 16:18:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/692_que-savait-moche-de-la-torah-des-rabbins.php</link> \n" +
                "\t<guid>LEAVA-COURS-692</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/269.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>Epreuve - épreuve... d'amour</title> \n" +
                "\t<description>Epreuve - épreuve... d'amour</description> \n" +
                "\t<pubDate>Wed, 11 Jan 2012 17:41:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/691_epreuve-epreuve-d-amour.php</link> \n" +
                "\t<guid>LEAVA-COURS-691</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/294.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>2ème partie - Séparation hommes - femmes dans le bus: Tolérance!</title> \n" +
                "\t<description>2ème partie - Séparation hommes - femmes dans le bus: Tolérance!</description> \n" +
                "\t<pubDate>Fri, 06 Jan 2012 12:33:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/689_2eme-partie-separation-hommes-femmes-dans-le-bus-tolerance.php</link> \n" +
                "\t<guid>LEAVA-COURS-689</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/80.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "<item> \n" +
                "\t<title>1ère partie - Séparation hommes - femmes dans le bus: Tolérance!</title> \n" +
                "\t<description>1ère partie - Séparation hommes - femmes dans le bus: Tolérance!</description> \n" +
                "\t<pubDate>Wed, 04 Jan 2012 17:29:00 +0100</pubDate> \n" +
                "\t<link>http://www.leava.fr/cours-torah-judaisme/pensee-juive/688_1ere-partie-separation-hommes-femmes-dans-le-bus-tolerance.php</link> \n" +
                "\t<guid>LEAVA-COURS-688</guid> \n" +
                "\t<enclosure url=\"http://www.leava.fr/img/screenshots/226.jpg\" length=\"0\" type=\"image/jpeg\" /> \n" +
                "</item> \n" +
                "</channel> \n" +
                "</rss>").getBytes();
        return new ByteArrayInputStream(bytes);*/
    }

    /**
     * Méthode permettant de retourner ce que contient d'un noeud
     *
     * @param _node le noeud principal
     * @param _path suite des noms des noeud sans espace séparer par des "|"
     * @return un string contenant le valeur du noeud voulut
     */
    public String readNode(Node _node, String _path) {

        String[] paths = _path.split("\\|");
        Node node = null;

        if (paths != null && paths.length > 0) {
            node = _node;

            for (String path : paths) {
                node = getChildByName(node, path.trim());
            }
        }

        if (node != null) {
            return node.getTextContent();
        } else {
            return "";
        }
    }

    /**
     * renvoye le nom d'un noeud fils a partir de son nom
     *
     * @param _node noeud pricipal
     * @param _name nom du noeud fils
     * @return le noeud fils
     */
    public Node getChildByName(Node _node, String _name) {
        if (_node == null) {
            return null;
        }
        NodeList listChild = _node.getChildNodes();

        if (listChild != null) {
            for (int i = 0; i < listChild.getLength(); i++) {
                Node child = listChild.item(i);
                if (child != null) {
                    if ((child.getNodeName() != null && (_name.equals(child.getNodeName()))) || (child.getLocalName() != null && (_name.equals(child.getLocalName())))) {
                        return child;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Afficher une Date GML au format francais
     *
     * @param gmtDate
     * @return
     */
    public String GMTDateToFrench(String gmtDate) {
        try {
            SimpleDateFormat dfGMT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
            dfGMT.parse(gmtDate);
            SimpleDateFormat dfFrench = new SimpleDateFormat("EEEE, d MMMM yyyy HH:mm:ss", Locale.FRANCE);
            return dfFrench.format(dfGMT.getCalendar().getTime());
        } catch (ParseException ex) {
            LOGGER.log(Level.SEVERE, null, ex);
        }
        return "";
    }

    /**
     * Exemple
     *
     * @param args
     */
    public static void main(String[] args) {
        final RSSReader reader;
        final RSSFeed rssFeed;
        reader = new RSSReader();
        rssFeed = reader.parse("http://confluence-eqd.bfi.echonet/confluence/");
        System.out.println(rssFeed.getTitle());
        System.out.println(rssFeed.getDescription());
        System.out.println(rssFeed.getLink());
        for (RSSItem rssItem : rssFeed.getRssItems()) {
            System.out.println(rssItem.getTitle());
            System.out.println(rssItem.getDescription());
            System.out.println(rssItem.getGuid());
            System.out.println(rssItem.getLink());
            System.out.println(rssItem.getPubDate());

        }
//        reader.parse("http://www.leava.fr/rss/cours-torah-judaisme/pensee-juive.xml");
//        reader.parse("http://fobec.com/CMS/fobec.xml");
    }
}

